package com.yanyeori.framework.web.http.accept;

import com.yanyeori.framework.core.constant.BaseConstant;
import com.yanyeori.framework.core.context.TraceContext;
import com.yanyeori.framework.core.context.UserContext;
import com.yanyeori.framework.core.model.WebResponse;
import com.yanyeori.framework.core.util.HttpUtil;
import com.yanyeori.framework.core.util.JacksonUtil;
import com.yanyeori.framework.core.util.StringUtil;
import com.yanyeori.framework.web.filter.FilterHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 请求头信息传递，设置上下文 拦截器处理器
 *
 * @author chenkuan 2021/7/29
 */
public class HttpHeaderContextHandler extends FilterHandler {

    @Override
    protected void configure(FilterManager filterManager) {
        filterManager
                .addBeforeFilter((request, response) -> {
                    handleContext(request, response);
                    return WebResponse.ok();
                })
                .addAfterFilter((request, response) -> {
                    clearContext(request, response);
                    return WebResponse.ok();
                });
    }

    /**
     * 重写该方法以处理自定义Context
     *
     * @param request HttpServletRequest
     */
    protected void handleContext(HttpServletRequest request, HttpServletResponse response) {
        //默认的Context处理
        handleUserContext(request, response);
        handleTraceContext(request, response);
    }

    /**
     * 重写该方法以清除自定义Context
     */
    protected void clearContext(HttpServletRequest request, HttpServletResponse response) {
        //默认的Context处理
        clearUserContext(request, response);
        clearTraceContext(request, response);
    }

    protected void handleUserContext(HttpServletRequest request, HttpServletResponse response) {
        UserContext userContext = handleContextBean(request, UserContext.class);
        if (userContext != null) {
            UserContext.set(userContext);
        }
    }

    protected void handleTraceContext(HttpServletRequest request, HttpServletResponse response) {
        TraceContext traceContext = handleContextBean(request, TraceContext.class);
        if (traceContext != null) {
            TraceContext.set(traceContext);
        } else {
            traceContext = TraceContext.get(true);
        }
        request.setAttribute(BaseConstant.TRACE_ID, traceContext.getTraceId());
    }

    protected void clearUserContext(HttpServletRequest request, HttpServletResponse response) {
        UserContext.clear();
    }

    protected void clearTraceContext(HttpServletRequest request, HttpServletResponse response) {
        TraceContext.clear();
        request.removeAttribute(BaseConstant.TRACE_ID);
    }

    /**
     * 处理ContextBean
     *
     * @param request HttpServletRequest
     * @param clazz   对象类型
     */
    protected <T> T handleContextBean(HttpServletRequest request, Class<T> clazz) {
        try {
            return handleContextBean(request, clazz, true);
        } catch (RuntimeException e) {
            return handleContextBean(request, clazz, false);
        }
    }

    /**
     * 处理ContextBean
     *
     * @param request    HttpServletRequest
     * @param clazz      对象类型
     * @param jsonFormat 是否进行json格式化处理
     */
    protected <T> T handleContextBean(HttpServletRequest request, Class<T> clazz, boolean jsonFormat) {
        String header = request.getHeader(BaseConstant.HEADER_PRE + clazz.getSimpleName());
        if (StringUtil.isEmpty(header)) {
            return null;
        }
        return jsonFormat ? JacksonUtil.parseObject(HttpUtil.decodeUrl(header), clazz) : (T) header;
    }
}
